package alkaid.eis.sys.service;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.TreeMap;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import alkaid.eis.common.exceptions.EntityMissingException;
import alkaid.eis.sys.core.SysEisException;
import alkaid.eis.sys.entity.Area;
import alkaid.eis.sys.entity.AreaComparator;
import alkaid.eis.sys.repository.AreaRepository;
import lombok.RequiredArgsConstructor;

/**
 * 地区服务
 * 
 * @author Lucky Yang
 * @since 0.0.1
 */
@Service
@RequiredArgsConstructor
public class AreaService {
    private final AreaRepository areaRepository;

    @Transactional(rollbackFor = Exception.class)
    public Area save(String parentCode, Area data) {
        Optional.ofNullable(parentCode).map(id -> this.findByCode(parentCode)).ifPresent(p -> {
            data.setPcode(p.getCode());
        });
        return areaRepository.save(data);
    }

    @Transactional(rollbackFor = Exception.class)
    public Area update(Long id, Area area) {
        Area entity = this.findById(id);
        entity.copy(area);
        return areaRepository.save(entity);

    }

    @Transactional(rollbackFor = Exception.class)
    public void delete(Long areaId) {
        areaRepository.findById(areaId).ifPresent(area -> {
            if (areaRepository.countChildByPcode(area.getCode()) > 0) {
                throw new SysEisException("存在下级地区，不能删除");
            }

            areaRepository.delete(area);
        });

    }

    public Area findById(Long id) {
        return areaRepository.findById(id).orElseThrow(EntityMissingException::new);
    }

    /**
     * 获取所有地区全称， key=code, value=全称
     * 
     * @return
     */
    public Map<String, String> findFullName() {
        List<Area> allAreaList = areaRepository.findAll();
        // key=code, value=名称
        Map<String, String> allAreaMap = allAreaList.stream().collect(Collectors.toMap(Area::getCode, Area::getName));

        // key=id, value=全称
        Map<String, String> rslt = new TreeMap<>();
        allAreaList.stream()
                // 排序
                .sorted(AreaComparator.PATHCODE)
                .forEachOrdered(a -> {
                    String value = Stream.of(a.getPathCode().split(Area.PATH_SEP))
                            .map(allAreaMap::get)
                            .collect(Collectors.joining(Area.PATH_SEP));
                    rslt.put(a.getCode(), value);
                });

        return rslt;
    }

    public Area findByCode(String code) {
        return areaRepository.findByCode(code).orElseThrow(EntityMissingException::new);
    }
}
